using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.AddressableAssets.ResourceLocators;
using UnityEngine.UI;
using UnityEngine.AddressableAssets;
using TMPro;
using System.Threading.Tasks;
using System;

public enum LoadMode
{
    ByLocalDll,
    ByLocalAddressable
}

[Obsolete]
public class ProLaunch : MonoBehaviour
{
    private const string DLLPath = "Assets/GameRes/HotFixDll/";

    public Text update_progress;
    public Slider update_slider;

    private List<object> _updateKeys = new List<object>();

    [Tooltip("dll�ļ��ļ��ط�ʽ")]
    public LoadMode loadingMode = LoadMode.ByLocalAddressable;

    void Awake()
    {
        update_slider.value = 0;
    }

    void Start()
    {
        ILRuntimeHotFixMgr();
    }

    public async void ILRuntimeHotFixMgr()
    {
        await StartHotFix();
    }

    /// <summary>
    /// ����dll
    /// </summary>
    /// <returns></returns>
    public Task StartHotFix()
    {
        //�����ȸ���Դ
        UpdateCatalog();
        //����dll
        if (loadingMode == LoadMode.ByLocalDll)
        {
            //HotFixMgr.LoadHotFixAssembly();
        }
        else if (loadingMode == LoadMode.ByLocalAddressable)
        {
            byte[] dll = new byte[] { };
            byte[] pdb = new byte[] { };
            Addressables.LoadAssetAsync<TextAsset>(DLLPath + "Unity.Hotfix.dll.bytes").Completed += (handle) =>
            {
                dll = handle.Result.bytes;
                Addressables.LoadAssetAsync<TextAsset>(DLLPath + "Unity.Hotfix.pdb.bytes").Completed += (handle) =>
                {
                    pdb = handle.Result.bytes;
                    HotFixMgr.LoadHotFixAssembly(dll, pdb);

                    StartGame();
                };
            };
        }
        //������Ϸ
        return Task.CompletedTask;
    }

    public async void UpdateCatalog()
    {
        //��ʼ��Addressable
        var init = Addressables.InitializeAsync();
        await init.Task;
        //��ʼ���ӷ�����������
        var checkHandle = Addressables.CheckForCatalogUpdates(false);
        await checkHandle.Task;
        if (checkHandle.Status == AsyncOperationStatus.Succeeded)
        {
            List<string> catalogs = checkHandle.Result;
            if (catalogs != null && catalogs.Count > 0)
            {
                foreach (var catalog in catalogs)
                {
                    Debug.Log("catalog  " + catalog);
                }
                update_progress.text = "���¶Ա��ļ�����";
                var updateHandle = Addressables.UpdateCatalogs(catalogs, false);
                if (!updateHandle.IsDone && updateHandle.Status != AsyncOperationStatus.Failed)
                {
                    // ���ؽ���
                    float percentage = updateHandle.PercentComplete;
                    update_slider.value = percentage;
                }
                await updateHandle.Task;

                foreach (var item in updateHandle.Result)
                {
                    _updateKeys.AddRange(item.Keys);
                }
                update_progress.text = update_progress.text + "\n���¶Ա��ļ��������";
                update_slider.value = 1;

                StartCoroutine(DownAddressaabes());
            }
            else
            {
                update_progress.text = "û����Ҫ���µ���Դ";
            }
        }
        else if (checkHandle.Status == AsyncOperationStatus.Failed)
        {
            OnError("CheckForCatalogUpdates Error\n" + checkHandle.OperationException.ToString());
        }
        Addressables.Release(checkHandle);
    }

    public IEnumerator DownAddressaabes()
    {
        var downloadsize = Addressables.GetDownloadSizeAsync(_updateKeys);
        yield return downloadsize;
        Debug.Log("start download size :" + downloadsize.Result);
        update_progress.text = update_progress.text + "\n�����ļ���С" + downloadsize.Result;

        if (downloadsize.Result > 0)
        {
            var downloadHandle = Addressables.DownloadDependenciesAsync(_updateKeys, Addressables.MergeMode.Union);
            yield return downloadHandle;
            //await download.Task;
            Debug.Log("download result type " + downloadHandle.Result.GetType());

            while (!downloadHandle.IsDone)
            {
                if (downloadHandle.Status == AsyncOperationStatus.Failed)
                {
                    OnError("DownloadDependenciesAsync Error\n" + downloadHandle.OperationException.ToString());
                    yield break;
                }
                // ���ؽ���
                float percentage = downloadHandle.PercentComplete;
                update_progress.text = $"������: {Mathf.Round(percentage * 100)}%";
                update_slider.value = percentage;
                yield return null;
            }
            yield return downloadHandle;
            if (downloadHandle.Status == AsyncOperationStatus.Succeeded)
            {
                Debug.Log("�������!");
                update_progress.text = "�������: 100%";
                update_slider.value = 1;
            }

            //foreach (var item in download.Result as List<UnityEngine.ResourceManagement.ResourceProviders.IAssetBundleResource>)
            //{
            //    var ab = item.GetAssetBundle();
            //    Debug.Log("ab name " + ab.name);

            //    update_progress.text = update_progress.text + "\n ab���� " + ab.name;


            //    foreach (var name in ab.GetAllAssetNames())
            //    {
            //        Debug.Log("asset name " + name);
            //        update_progress.text = update_progress.text + "\n asset ���� " + name;
            //    }
            //}
            Addressables.Release(downloadHandle);
        }
        Addressables.Release(downloadsize);
    }

    IEnumerator DoUpdateAddressadble()
    {
        AsyncOperationHandle<IResourceLocator> initHandle = Addressables.InitializeAsync();
        yield return initHandle;

        // ������
        var checkHandle = Addressables.CheckForCatalogUpdates(false);
        yield return checkHandle;
        if (checkHandle.Status != AsyncOperationStatus.Succeeded)
        {
            OnError("CheckForCatalogUpdates Error\n" + checkHandle.OperationException.ToString());
            yield break;
        }

        if (checkHandle.Result.Count > 0)
        {
            var updateHandle = Addressables.UpdateCatalogs(checkHandle.Result, false);
            yield return updateHandle;

            if (updateHandle.Status != AsyncOperationStatus.Succeeded)
            {
                OnError("UpdateCatalogs Error\n" + updateHandle.OperationException.ToString());
                yield break;
            }

            // �����б������
            List<IResourceLocator> locators = updateHandle.Result;
            foreach (var locator in locators)
            {
                List<object> keys = new List<object>();
                keys.AddRange(locator.Keys);
                // ��ȡ�����ص��ļ��ܴ�С
                var sizeHandle = Addressables.GetDownloadSizeAsync(keys);
                yield return sizeHandle;
                if (sizeHandle.Status != AsyncOperationStatus.Succeeded)
                {
                    OnError("GetDownloadSizeAsync Error\n" + sizeHandle.OperationException.ToString());
                    yield break;
                }

                long totalDownloadSize = sizeHandle.Result;
                update_progress.text = update_progress.text + "\ndownload size : " + totalDownloadSize;
                Debug.Log("download size : " + totalDownloadSize);
                if (totalDownloadSize > 0)
                {
                    // ����
                    var downloadHandle = Addressables.DownloadDependenciesAsync(keys, Addressables.MergeMode.Union, false);
                    //yield return downloadHandle;
                    while (!downloadHandle.IsDone)
                    {
                        if (downloadHandle.Status == AsyncOperationStatus.Failed)
                        {
                            OnError("DownloadDependenciesAsync Error\n" + downloadHandle.OperationException.ToString());
                            yield break;
                        }
                        // ���ؽ���
                        float percentage = downloadHandle.PercentComplete;


                        Debug.Log($"������: {percentage}");
                        update_progress.text = $"������: {Mathf.Round(percentage * 100)}%";
                        update_slider.value = percentage;
                        if (percentage >= 0.9f)//����������Ѿ�����90%
                        {
                            update_slider.value = 1; //�Ǿ��ý�������ֵ����1
                        }

                        yield return null;
                    }
                    yield return downloadHandle;
                    if (downloadHandle.Status == AsyncOperationStatus.Succeeded)
                    {
                        Debug.Log("�������!");
                        update_progress.text = "�������: 100%";
                        update_slider.value = 1;
                    }
                }
            }
        }
        else
        {
            Debug.Log("û�м�⵽����!");
            update_progress.text = update_progress.text + "\nû�м�⵽����";
        }

        // ������Ϸ
        StartGame();
    }

    /// <summary>
    /// �����쳣��ʾ
    /// </summary>
    /// <param name="msg"></param>
    void OnError(string msg)
    {
        update_progress.text = update_progress.text + $"\n{msg}\n����ʧ�ܣ�";
    }

    /// <summary>
    /// ���³ɹ���������Ϸ
    /// </summary>
    void StartGame()
    {
        StartCoroutine(LoadGameScene());
    }

    IEnumerator LoadGameScene()
    {
        update_slider.value = 0;
        var handle = Addressables.LoadSceneAsync("Assets/Scenes/GameScene.unity");
        if (handle.Status==AsyncOperationStatus.Failed)
        {
            Debug.LogError(handle.OperationException.ToString());
            yield break;
        }
        while (!handle.IsDone)
        {
            float percentage = handle.PercentComplete;
            update_progress.text = $"���ڽ�����Ϸ��{percentage}";
            update_slider.value = percentage;
            yield return null;
        }
    }
}
